perm filename MMOTNS.PUB[HAL,HE]2 blob sn#132166 filedate 1974-11-24 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00014 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	.NEWSS MOTIONS
C00003 00003	.mrt: NEWSSS COMPILE-TIME AND RUNTIME CONSIDERATIONS
C00007 00004	.NEWSSS	SIMPLE MOVES
C00013 00005	.NEWSSS	CONDITION MONITORS
C00024 00006	.NEWSSS FORCE DURING A MOTION
C00032 00007	.dep: NEWSSS DEPROACHES
C00041 00008	.NEWSSS OTHER MOTION CLAUSES
C00049 00009	.NEWSSS	COMPLEX MOVES
C00054 00010	.NEWSSS SEARCHES
C00060 00011	.NEWSSS STOPPING
C00061 00012	.NEWSSS DEVICE CONTROL
C00066 00013	.aff: NEWSS AFFIXMENT
C00073 00014	.NEWSSS  MOTIONS AND AFFIXMENT
C00076 ENDMK
C⊗;
.NEWSS MOTIONS

Motion statements are at the heart of 'AL; it is by them
that all manipulatory work is done.  

.mrt: NEWSSS COMPILE-TIME AND RUNTIME CONSIDERATIONS

	All motion statements cause the compiler to make some plans
which will eventually be executed.  Those motions which depend on the
value of some frame expressions for intermediate and final position
will be planned using the compile-time planning values for all
relevant expressions.  This can lead to inaccurate plans, since at
runtime, some of those expressions might have different values.  An
example is an expression involving the location of the arm; the
variables %4yellow%* and %4blue%* are always kept accurate at runtime
by reading the arm locations.  Since every arm motion must begin at
the current arm position, this is an implicit parameter to the motion
specification which may not agree with its planning value.  This is a special
case of a general
phenomenon: objects are seldom exactly where they
were planned to be, and the runtime value of their frames will very
likely be based on the position of the hand after it successfully
locates the object by sensory feedback.

Thus it becomes necessary that the runtime system adjust all
trajectories immediately before they are executed.  Adjusting a
trajectory is less time-consuming than the original calculation;
it makes sense to adjust before each repetition of a motion, whereas
it would be a waste of computer time to recalculate trajectories
that often.  Immediately before the arm starts moving on a
trajectory, then, the plan is modified to bring it into line with
current values of frames.  If there is any discrepancy between the
runtime and compile-time understanding of where any frame is, the
servo will try to place the arm in the right place nonetheless.  

There are limits to the proper use of this feature; if the planning
value is seriously in error (which can happen if the error is but a few
centimeters, depending on the arm being used and its
configuration), then the attempt to make last-minute corrections might
overstrain the arm or impair response to directional
forces.  It is the user's responsibility to foresee large
discrepancies in the planning value and to 
program in a condition to select one of several possible moves.
Hopefully, this will be seldom needed.

After a motion has been completed, the new location of the hands will
be read, and that will determine the new value for %4yellow%* and
%4blue%*, as well as for any frames which might be affixed to them.
For the moment, we will ignore affixments; they are discussed in great
detail later. 

.NEWSSS	SIMPLE MOVES

	In this section we will discuss motions which are to be
executed on only one arm.
Let us start with an example:
.UNFILL
	FRAME frobgrasp, swing1, swing2;
	:
	MOVE yellow
		TO frobgrasp
		VIA swing1, swing2
.REFILL
This example demonstrates the general syntax; the reserved word MOVE
is followed by the name of the arm to be moved and a set of clauses,
each beginning with a reserved word (here the words TO and VIA).
There is no punctuation necessary at the end of a clause.  The arm is
expected to travel from its current position (wherever that is
planned to be) to the final position (%4frobgrasp%*), passing through
the intermediate positions (%4swing1%* and %4swing2%*).  A smooth
trajectory for the motion will be computed by splining together
polynomial segments (usually third degree, occasionally fourth)
separately for each arm joint.  This trajectory calculation is
somewhat time-consuming and is done completely at compile time. 

	Certain things must be specified for any move.  First is the
arm which is to be moved.  It is named by an arm frame (%4yellow%* or
%4blue%*); other ways of specifying the arm will be mentioned after
the formal idea of affixment has been presented. 
Next, the destination frame must be specified. "TO#%4frobgrasp%*"
means that at the end of the motion, the position of the arm should
coincide with the position of %4frobgrasp%*.  There is a notational
convenience for destinations: They can be specified in terms of where
the arm is at the start of the motion.  The symbol for this is "⊗"
(sometimes pronounced "grinch"), that is, ⊗ is a frame which has the
location and orientation of the arm at the start of the motion. 
Thus, 
.UNFILL
	MOVE yellow TO ⊗ + Z*CM
.REFILL
will move the arm 1 centimeter in Z above  its starting place.

.NEWSSS	CONDITION MONITORS

	During the course of an arm motion, it may be desired to monitor
some condition or set of conditions in order to prematurely stop the
motion or inform some parallel process that a condition has occurred.
The conditions which may be checked are results of measurements, such
as time or force checking, and %4events%*, which are signals that
can be explicitly sent by other simultaneous processes.  Events
will be discussed in {sssref evt}; for the time being, assume that
the only conditions which may be checked are measurement conditions.
Here is an example which contains some %4condition monitors%*:
.UNFILL
	SCALAR warning;
	VECTOR v1;
	:
	MOVE yellow
		TO ypark
		ON DURATION ≥ 3*SEC DO warning ← 1
		ON FORCE(v1) ≥ 18*OZ DO STOP α{%4Stops the arm%*α}
.REFILL
This motion has two separate and independent condition monitors; the
first will trigger if the motion takes longer than three seconds, and
the second will trigger if the force on the hand, as measured along
vector %4v1%*, exceeds 18 ounces. (Assume we have a macro which
translates ounces into units of force.)
The %4conclusion%* of a condition monitor,
the code which will be executed if the monitor triggers,
is one statement prefaced with the reserved word DO.

A condition monitor  has two states: %4enabled%*  and
%4disabled%*. Generally,   a condition monitor  will be enabled as  soon as its
motion statement is  started,   and it becomes  disabled when  the
motion ends. As soon as a condition monitor triggers, it becomes
disabled unless it becomes explicitly reenabled.  Reenabling is done by executing
the statement ENABLE within the  conclusion.

In order to enable or disable some arbitrary monitor, it is necessary
to give it a name; this is done by putting a %4label%* immediately
before the word ON.  A label is an undeclared identifier followed by
a colon.  Thus we could write:
.UNFILL
	MOVE blue TO frobgrasp
		test1: ON DURATION ≥ 3*SEC DO DISABLE test2
		test2: ON TEMPERATURE < 30 DO STOP 
.REFILL
Thus, test2  is only performed for the first three seconds.

Occasionally one wants to write a condition monitor which is initially
disabled and becomes enabled later.  This is accomplished by putting
the word DEFER before ON:
.UNFILL
	fudge: ON temperature > 400 DO 
		BEGIN  α{%4Keep shouting until someone hears.%*α}
		WRITE("BURNING");
		STOP OVEN;  α{%4Pretend we have a device OVEN%*α}
		ENABLE  α{%4This reenables %*fudgeα}
		END
	taste: DEFER ON cooked α{%4This is an event.%*α} DO DISABLE fudge
	ON DURATION > 30*MIN DO ENABLE taste
.REFILL
	It should be  noted that this  ability to enable  and disable
monitors explicitly is  a non-structured construct; using it can
lead to unintelligible programs.   In any  case, scope rules must  be
observed;  it is  not  legal to  enable  or disable  monitors across
different MOVE statements.  This  means  that  two  motion statements
which happen to be simultaneously executing (we shall see how to do this
later, in {sssref cob}) cannot
interfere with each other's condition monitors.

Boolean combinations of conditions are not allowed.  Some of the
continually measured functions which may be tested are force along a
vector, (FORCE(V)), force about an axis (TORQUE(V)), time since
beginning of motion (DURATION), and the force between the fingers
(SQUEEZE).  One standard event is testable: ARRIVAL.  This event
occurs when the motion terminates due to having reached its
destination.  It does %4not%* become true if the arm stops for
reasons other than normal arrival at the destination; STOP does not
trigger it. 

	The conclusion of a condition monitor may be any statement,
including an entire block.  The only restriction is that if a motion
statement is the only statement in the conclusion, it must be
surrounded by BEGIN and END.  (This is necessary at times to prevent
ambiguity.) The compiler will complain if you try to embed a motion
statement inside another if the result implies simultaneous motion
statements for the same device. 

	The existence of condition monitors raises this question: When is the
motion really finished?  It  can  happen that  the arm itself has stopped,
but some monitor has triggered, and its conclusion is still busy being
executed.  The rule is this: the motion is declared done when all the
joints of the arm are stopped, and all monitors are either disabled or
not currently triggered.
Any monitors still enabled, but not triggered, are disabled at the time
that the motion is declared finished.

	The user must be aware of some timing considerations.
Firstly, measurements like FORCE, DURATION, and SQUEEZE are not
really computed continually; there is a process which makes a
measurement and then lies dormant for a while (on the order of twenty
milliseconds) before again making a measurement.  Thus, monitors do
not trigger immediately when a tested condition becomes true.
Secondly, when a monitor triggers, any initial statements of enabling
or disabling are done immediately, but any arithmetic is scheduled to
be done at some point in the near future.  Therefore it is not
possible to guarantee that a critical computation happen immediately.
If the user desires, he may use the word CRITICAL at the start of the
conclusion, and UNCRITICAL at the start of that code which need not
be guaranteed immediate execution.  Only one occurrence of CRITICAL,
at the very start of the conclusion, and only one occurrence of
UNCRITICAL are allowed.  'AL automatically assumes CRITICAL before
initial statements of enabling and disabling, and UNCRITICAL
immediately following.  An example:
.UNFILL
	ON DURATION ≥ 4*SEC DO		α{%4Tested frequently%*α}
		BEGIN 
		ENABLE goodguy;		α{%4Assumed CRITICAL%*α}
		t ← 3;			α{%4Assumed UNCRITICAL%*α}
		END 
	ON SQUEEZE ≥ 10*OZ DO		α{%4Tested frequently%*α}
		BEGIN
		CRITICAL;  		α{%4Overrides defaults%*α}
		t ← 4;			α{%4Will be done immediately%*α}
		UNCRITICAL;		α{%4End of critical region%*α}
		DISABLE goodguy;	α{%4Done soon%*α}
		END 
.REFILL

.NEWSSS FORCE DURING A MOTION

To make the arm compliant to external forces along some directions or
about some axis it is necessary to specify the appropriate modes of
freedom.  Because 'AL works in three-dimensional space, it only
makes sense to specify at most three orthogonal directions and three
orthogonal axes.  
In addition to being compliant along degrees of freedom (whether translational
or rotational), it is also useful to apply a fixed force along some of
these degrees.  Then pure freedom reduces to application of zero force.

For example, 
suppose the arm is on the surface of the station; we wish to apply 
a force of 10000 dynes directly downward (the negative Z direction) while
allowing the arm to comply to  any horizontal force.  This is how
we would write such a motion:
.UNFILL
	MOVE blue TO ⊗  α{%4moves nowhere%*α}
		WITH DURATION = 10*SEC  α{%4give it some time.%*α}
		WITH FORCE = -10000*DYNES ALONG Z OF station 
		WITH FORCE = 0 ALONG X, Y OF station
.REFILL
This example illustrates several conventions.  A translational degree
of force (or freedom, if the amount of force is zero) is specified
by the word ALONG followed by a list which can only contain the
vectors X, Y, and Z, followed by the word OF and the name of the
frame which specifies the coordinate system in which the cardinal
axes are to be understood.  The amount of force must be in force
units, which are of the scalar dimension 
%4mass*distance/(time*time)%*; we
have assumed in the example above that DYNES is a macro which
expands to correct units.

Rotational degrees of force are written in much the same way; the
axes are specified ABOUT a combination of X, Y, and Z OF some frame,
like this:
.UNFILL
	WITH FORCE = 5000*DYNES ABOUT Z OF ⊗
.COMT 12
	α{Applies a torque about the Z direction of the hand.α}
.END
.REFILL
During a motion which has only translational force specifications, the
orientation of the hand will remain as planned, but the location will
comply with the specified force.  During a motion which has rotational
degrees of force, the orientation of the hand will vary from that
planned in accord with the specification and whatever external forces
are encountered.

It does not really make sense to have a force in the nominal direction of motion,
but there is neither a compile-time nor a runtime check to catch such
usage.  If it happens, the arm could go into oscillation.

Actually, not all of the full power of force specifications will be available
in the first versions of 'AL.  In particular, rotational specifications
will be handled roughly or not at all.  Another future embellishment
will be to allow the directions of force to vary during the motion; this
is useful for such tasks as turning a crank.  For example, the following
will eventually be available:
.UNFILL
	MOVE yellow TO frobgrasp
		WITH FORCE = SIN(DURATION*DEG)*10000*DYNES 
			ALONG Z OF @;
.REFILL
This specifies a varying amount of force along a varying direction:
"@" means "the %4current%* location of the hand, as it changes during
the motion."  

Especially at first, some of the force control will be prepared by
the compiler, not calculated during the arm motion itself.  Therefore,
if the runtime values of the endpoints of motion are significantly
at odds with their planning values, application of force may go awry.

.dep: NEWSSS DEPROACHES

	Many objects  have shapes which  necessitate care as  the arm
approaches  them or departs from  them.  'AL supplies  a method for
insuring that every  time the arm  approaches a  frame, it will  pass
through an  associated spot  first, and every  time it  leaves that
frame,   it passes once  again through the same spot.   The "spot" is
termed a %4deproach%*  (from %4dep%*arture  and ap%4proach%*); it is 
a transformation  to  be applied  to  the frame  involved  in order  to
discover the appropriate place through which to pass.
The fact that a trans is used implies that the deproach point will move
about with its frame.  It also means that the location of the deproach
point is relative not to the origin of the frame, but rather to the point
in frame coordinates to which the motion leads.  For example, the 
deproach transformation of the station is TRANS(VECTOR(0,0,10*CM),NILROT).
If the arm is to go to, say, the point VECTOR(3,1,4)+station
using station's deproach,
 then
it will first go through VECTOR(3,1,14).  This has the effect of
preventing the arm from going through the surface of the station.

The deproach of a frame is specified by means of an assertion.  Without
going into full detail on assertions (which will be covered in detail
in {ssref asr}), we give some examples:
.UNFILL
	ASSERT FORM(DEPROACH, station, TRANS(NILROT,VECTOR(0,0,10*CM));
.COMT 12
	α{This is preasserted and need never be included.α}
.END
	ASSERT FORM(DEPROACH, frob, TRANS(ROT(X,90*DEG),VECTOR(1,0,0)));
.COMT 12
	α{Whenever you go to frob, go through a point 
	90 degrees about frob's X axis from a spot one
	centimeter in X from the nominal arrival point.α}
.END
.REFILL
	Note that since deproaches are transformations, they have the  power to
include  rotations. These  are considered to  be rotations  about the
origin of  the coordinate system  involved; the  rotation occurs,  as
usual, before translation.
The use of rotations is of marginal use, but is included for completeness.

The deproach points of the departure frame and the arrival frame
are used as implicit VIA points for any motion, except when
the destination is "⊗" or there is an overriding deproach clause
in the motion statement.  Here are some examples:
.UNFILL
	MOVE yellow TO ⊗;  α{%4No departure or approach point used%*α}

	MOVE yellow TO frob
		WITH APPROACH = NILDEPROACH;
.COMT 20
		α{The default departure (which depends on the last
		motion made by yellow) is used, but no approach point
		is desired.α}
.END

	MOVE blue TO frob
		WITH DEPARTURE = NILDEPROACH
		WITH APPROACH = DEPROACH(frobgrasp);
.COMT 20
		α{No departure point is desired, but the approach should be
		as if the destination were frobgrasp, not frob.α}
.END
.REFILL

	Suppose that a frame
f  is given  deproach transformation d.   It  is desired to  find the
frame which  is  the deproach  point from  some  other frame  h  (for
example, where the hand is, for  departure), using f's deproach.  The
frame  which  will be used as a via point is this:
.UNFILL
	f  *  d  * (f → station)  *  h    .
.REFILL

The deproach point for f itself is discovered by setting h#=#f in the
above expression.  The identities
.UNFILL
	(f → station) * f = station, and a * station = a     .
.REFILL
reduce the resulting expression to f * d; this is therefore f's own
deproach point.


We have not yet discussed affixment of frames, but the actual decision
of which deproach to use in a given situation depends on it somewhat,
so let us just mention that there is a way to specify that two
frames are affixed, so that whenever on moves, so does the other.
Exact details are given in {ssref aff}.  With this understanding,
we can describe the method used to describe how 'AL determines
what deproach to use:

	When an arm moves %4to%* a frame,
the frame's own deproach is used, if it has one.  If
not, then a search is made along the string of affixments (that is, frames
to which the given frame is affixed are searched) until one is found
which has a deproach.  That deproach is the one that is used.
If none  at all is found,  then the station's
deproach is  used as a  default.   (One way  to think of  this is  to
consider all frames ultimately  affixed to the station.) In approaching
a frame which  is  the  result of a  calculation, as in  
.UNFILL
	MOVE yellow TO frob + VECTOR(0,0,1)	,
.REFILL
 the default approach is NILDEPROACH.
The default deproach of ⊗ is also null.

	In departing %4from%* a frame,  it  matters whether or not that frame is
now attached to the hand.  If not, then the same algorithm used for
finding departure is used for approach. But if the frame
has been detached  from some erstwhile mother and is  now attached to
the  hand,  then its  old mother's deproach is used  (and if there is
none, the same search is  made).  
Thus, a frame
attached to the hand still has some "memory" of its previous state of
attachment.

.NEWSSS OTHER MOTION CLAUSES
	Here we describe some of the other additional clauses that
may be associated with motion statements.  The first is WITH
DURATION, which allows the user to specify the timing for the motion. 
One can use ≥,=, or ≤ for duration control.  The first is used to
guarantee that the motion take a certain amount of time, that is, it
guarantees that the motion will be slow enough so that all the time
is used.  The second is rarer; it is used when the exact time is
somehow critical.  If the compiler thinks that the arm cannot move
fast enough, it will complain.  The third form is included primarily
for completeness; once again, it can cause the compiler to complain.
In the absence of any timing specification, 'AL will compute the
least time which will allow the particular arm being used to move
most efficiently. 

VIA is used to name desired 
points along the trajectory.
In its simplest form, the VIA clause contains merely a list of frame
expressions, such as in this example:
.UNFILL
	MOVE yellow TO finalpoint
		VIA int1, int2 + VECTOR(0,0,1), int3;
.REFILL
The motion will be planned to go from the current location of the yellow
arm, through a departure point (if there is one), through each of
the intermediate frames, through the approach point (again, if there
is one), and finally to arrive at finalpoint.

At each of the intermediate points, it is possible to specify
the velocity to be achieved at that point (in terms
of a velocity vector) as well as upper or lower bounds on the time
used to reach this frame from the previous one on the list.
Here is an example demonstrating these features:
.UNFILL
	MOVE blue TO finalpoint
		VIA int1 WHERE VELOCITY = velo1, DURATION = 3*SEC
		VIA int2 WHERE DURATION ≥ 7*SEC
		WITH DURATION ≥ 10*SEC;
.REFILL
This specifies two intermediate points, each of which has some condition
associated with it.  A time constraint for the entire motion is also
given. Note that the word VIA must be repeated when conditions are
specified for some intermediate point.

One final feature is available with respect to intermediate points:
One may specify that a  piece of  code is to  be initiated when any
intermediate
point is achieved.  This is done with a THEN construct:
.UNFILL
	MOVE red TO rpark
		VIA int1 THEN WRITE("Almost there!")
		VIA int2 THEN ENABLE prepare_for_landing;
.REFILL
  The statement
following THEN may not be  a motion statement for  the same
arm; if the statement is a motion statement, it must be surrounded
by BEGIN and END.  It is legal to have combinations of velocity,
duration, and THEN-type specifications all at the same intermediate
point.

	DIRECTLY is a clause that 
tells the compiler that only the via points and the
final point are of interest; no smooth trajectory need be planned.
A smooth motion will result due to runtime calculations.
This will also set the deproaches to NILDEPROACH.

	TRACING  is another  option.    It  allows the  user  greater
control over the  exact trajectory chosen for the move.  The path can
be traced at whatever  speed desired.   The path,  or  %4parameterized
frame%*,  is  a specification of what  frame the arm is  to go through
for each  value of the parameter.  It is also possible to specify the
relation between the parameter and real time, as well as the
state the  grain of the motion 
(that is, how often the actual location should coincide exactly with
the parameterized frame)
or the acceptable tolerance (by a distance scalar). 
A glorious and complete example:
.UNFILL
	ANGLE SCALAR alpha;
	FRAME center;
	:
	MOVE yellow  α{%4No destination specified with a tracing motion.%*α}
		TRACING center + 12*VECTOR(COS(alpha),SIN(alpha),0)
		FOR alpha ← 0 BY 10*DEG UNTIL 360*DEG
		WITHIN .1*CM  α{%4This is the tolerance.%*α}
		WITH DURATION = 10*SEC;
.REFILL
This specifies a circular motion of radius twelve centimeters parallel
to the surface of the station, about the frame %4center%*.  Every
10 degrees, the arm should actually be in the right place, and, furthermore,
it should never be more than .1 centimeter (pretty tight tolerance, actually;
most likely beyond the capability of the manipulator) from the perfect
circle.

	The option  MAINTAINING ORIENTATION causes
the trajectory computed  by 'AL to  try to  maintain the same
hand orientation  throughout  the motion.    Of  course,   the  final
orientation must be  the same as the initial orientation  for this to
work at all.

.NEWSSS	COMPLEX MOVES

	A complex move is  one which involves more than one  arm at a
time.  A distinction can be  made between moves  which merely require
simultaneous acquisition of "agreement points" (let us call this weak
synchrony),  and   those  which   require  true   coordinated  motion
throughout (strong synchrony).

	Weak synchrony is achieved by pairing frames to make composite
VIA points and destinations.  A paired frame  has the form: [F1 : F2].
Here is an example of a move statement using paired frames:
.UNFILL
	FRAME y1, y2, y3, y4, b1, b2, b3;
	:
	MOVE [yellow : blue]
		VIA [y1:b1],[y2:],[y3:b2]
		TO [y4:b3]
		ON [FORCE(Z)>3000*DYNES:] DO STOP
.REFILL
	The via list is  composed of a set of paired  frames, where an empty field
indicates  "don't  care".   In  the  example  shown,  the arms  start
together, achieve  y1 and b1  simultaneously, the  yellow arm  passes
through y2, and together they pass through y3 and b2.  

	It  is  now  more  cumbersome  to  specify  condition monitors and
conditions  in general.   The  paired construct  applies for  all the
optional fields; thus, one can write
.UNFILL
	WITH FORCE = [14000*DYNES:] ALONG [X OF yellow:]
.REFILL

	The meanings of ⊗ and @ are now relative to which side of  the
pair they occupy; in  the example above, the left  side always refers
to the yellow arm,  and the right side to the blue.  To override this
convention, one may use expressions like "@.yellow", or "⊗.blue".

	The meaning of STOP in the example above is extended  to both
arms at once;  in order to specify  only one, it is  necessary to say
"STOP yellow" or "STOP blue".

	Strong synchrony involves one concept not included above: The
ability to  specify the location of one  arm throughout the motion in
terms of the location of the  other arm.  The construct which  allows
this  specification  is  COORDINATING;  it allows  one  to  give  an
expression for  the location of one of the two arms.  Suppose we wish
to keep both arms in "lockstep", that is, the  blue arm should retain
its relative position to the yellow arm throughout the motion.  (This
might be necessary for lifting some object by its two ends.) One  way
to code this task is as follows:
.UNFILL
	FRAME y1, yint1, yint2;
	MOVE [yellow : blue]
		TO [y1:]
		VIA [yint1:],[yint2:]
		COORDINATING LOC(blue) = LOC(yellow) + ⊗.blue - ⊗.yellow
		WITH FORCE = [:0] ALONG [: X,Y OF blue]
		[MAINTAINING ORIENT : MAINTAINING ORIENT]
.REFILL

.NEWSSS SEARCHES

	A  SEARCH is  very  much like  a  move.   It  is a  means  of
specifying  repeated action  in a  spiral.  As  with a  MOVE,   it is
necessary to name a controllable frame which is to be moved.   The ON
construct is exactly as for MOVEs.

Here is a complete example of a search:
.UNFILL
	PLANE p1;
	:
	SEARCH yellow
		ACROSS p1
		WITH INCREMENT = 3*CM
		REPEATING 
			BEGIN  α{%4This is done at each iteration%*α}
			FRAME set;
			set ← yellow;
			MOVE yellow TO ⊗ - Z
				ON FORCE(Z) > 3000*DYNES DO TERMINATE;
			MOVE yellow TO set DIRECTLY;
			END
.REFILL
The plane of the search is specified by the ACROSS construct.  A spiral
box search will be performed in this plane (or parallel to it, it the
initial location of the hand is not in the plane); the increment for
the search will be three centimeters.  At each point in the search, the
statement following REPEATING is executed; in this case, that involves
two motions.  The special statement TERMINATE causes the search to
finally succeed; if there is an ON ARRIVAL clause in the search, it
will trigger when TERMINATE is executed.
It is also possible to terminate a search by setting some flag inside
the repeated code, and to test it in a condition monitor associated
with the search.  That monitor can execute the statement STOP, causing
the search to be halted.  In this case, any test for ARRIVAL will
never trigger.

.NEWSSS	CENTER

	Occasionally the hand is positioned around an object, but it
is not certain if it is centered.  One wants to close the fingers
slowly, moving the arm meanwhile to accomodate to the location of
the object.  
This  is accomplished by means of the CENTER command.
The direction that the hand will move is the direction between its
fingers.  All that the CENTER command needs is the name of the
arm being moved.
The use of  ON is the same as for a
search or any other motion.

	Here is a simple example:
.UNFILL
	CENTER blue
		ON SQUEEZE > 4 DO STOP
.REFILL
Note that this is command, unlike MOVE, treats the fingers and
the arm together as one device.

.NEWSSS	CONSTANT VELOCITY MOTION

	A special form of the MOVE instruction is provided
to cause  the arm to  quickly achieve a  particular velocity
and to hold it in straight-line motion for a given distance:
.UNFILL
	VELOCITY VECTOR vv1;
	VECTOR v1;
	FRAME dest;
	:
	MOVE yellow
		WITH VELOCITY = vv1
			THROUGH dest
			FOR DISTANCE = 4*CM		.
		ON FORCE(v1) > 2000*DYNES DO STOP
.REFILL
The VELOCITY clause tells which  vector to follow,  and how  fast. The
THROUGH clause tells the compiler where the move  expects to end. The FOR
DISTANCE tells the maximum distance the hand should go. It is general practice
to terminate such a move by use of a condition monitor.

.NEWSSS STOPPING

	Generally, an arm will  stop its motion when it  has achieved
its destination.   Often it is necessary  to stop it prematurely, for
example, if some  error condition  is detected.   The statement  
.UNFILL
	STOP yellow 
.REFILL
causes the  yellow arm to be unconditionally  stopped; any
motion statement operating it will terminate.
This statement may be executed at any point in the program, not just
inside a motion statement.

.NEWSSS DEVICE CONTROL
 Each device has a name;
currently, the legal device  names are
%4yellow, blue, vice, driver%* (an  electric  screwdriver), %4yfingers,
bfingers%* (The fingers of the two arms). STOP without any device  name
is only legal within a motion command;  it stops whatever device(s) that
command is operating.  STOP followed by a device name will unconditionally
stop that device.

	There is a  general command for operating devices  other than
arms; it is hoped that this will be flexible enough for any device we
are likely to use (if not, we will add special new forms).  Assume we
have the device %4turntable%*, which is capable of moving at any velocity
and  for any length of time, but which  cannot go to a particular set
point.  Then the syntax would be this:
.UNFILL
	OPERATE turntable
		WITH VELOCITY = 3*DEG/SEC
		WITH DURATION = 8*SEC
.REFILL
The idea is that  the WITH construct will suffice to  account for any
special  data (in this case,  velocity and duration)  peculiar to the
particular  device.    The  OPERATE  statement  also  allows  the  ON
construct, so it can test for special conditions and take appropriate
actions; it also always allows WITH DURATION.

	The screwdriver is a  hand-held device which can be  run at a
range  of speeds,  in either  direction.   By convention,  a positive
velocity   means   clockwise,   and   a   negative   velocity   means
anticlockwise.  The  relevant reserved  word  is  VELOCITY, which  is
equated  with the name  of a  scalar variable of dimension
%4angle/time%*.  This variable  will be queried
periodically during the screwdriver motion to determine  how  much
voltage  to apply to the  motor.   This allows  the velocity  to change
during the operation of  the device, perhaps under  the control of  a
parallel process which is monitoring some conditions.
	An example:
.UNFILL
	OPERATE driver
		WITH VELOCITY = sp
		WITH DURATION = 4*SEC
		ON DURATION>2*SEC DO sp ← 2*sp 
.COMT 16
		α{After two seconds, speed up the screwdriver.α}
.END
.REFILL

	Each arm  has two  fingers at  the end  which are capable  of
closing and  opening at various speeds.   The relevant reserved words
are OPENING, which is to be set to the desired (distance scalar) opening,  and
VELOCITY, which is to be set to the (velocity scalar)
speed desired.  It is possible to
refer to the force scalar variable SQUEEZE, which indicates the force being
applied by the fingers.
Condition monitors can also make use of the distance scalar variable
OPENING which will continually reflect the distance between the fingers.
	An example:
.UNFILL
	OPERATE yfingers
		WITH OPENING = 2*IN
		WITH VELOCITY = 2*CM/SEC
		ON SQUEEZE > 3*OZ DO STOP
		ON OPENING ≤ 1*CM DO STOP
.REFILL

.aff: NEWSS AFFIXMENT
.newsss THE AFFIX STATEMENT

	Assembly often involves affixing  one object to another.  'AL
has a mechanism to automatically keep  track of the location of  a
subsidiary piece of the assembly as its  base is moved; the mechanism
is  called %4affixment%*.   For example, there  might be  a frame called
pump and a  frame called base.   At some stage  in the assembly,  the
pump  is bolted  to the  base.   At this  time it  is appropriate  to
include the statement 
.UNFILL
	AFFIX pump TO base	.
.REFILL
This statement informs the compiler  that
motions of base  are to affect the location of pump
causes code  to be  generated  for the  runtime which  will
automatically  update the value of  pump every time  base is changed.
Finally, the planning model will be updated to reflect the affixment.
A slightly more formal definition of affixment, in terms of 
explicit assertions and modifications to the runtime graph structure,
is given in {sssref gaf}.

Please note  that the  AFFIX statement  does not  act  as a  library
routine invocation; it does not generate code to actually perform the
bolting operation.   The statement merely informs the 'AL system that
at  this stage  in  the  execution of  the  program,  pump is  to  be
considered affixed to base.

	If pump  should be moved while affixed to base, the value of
base itself will not change,  but the affixment will remain  for the
new relative positions of pump  and base.  Occasionally it is desired
that the affixment be symmetric, so that motion of either frame will
cause the other to move.  This is done by including the reserved word
RIGIDLY in the affix statement: 
.UNFILL
	AFFIX pump TO base RIGIDLY
.REFILL
The system uses a trans to store the relative positions 
(in our example, (base#α→#pump) ) of the 
affixed frames.  Normally, the system would invent a 
temporary variable to hold this trans; however, the user can 
supply his own variable to be used instead, thus allowing his
to modify the affixment relation directly.  This is done by including
the phrase "BY#<trans#variable#id>" in the AFFIX statement.
For instance,
.UNFILL
	TRANS t1;
	:
	AFFIX pump TO base BY t1;
.REFILL
	If the value of  the trans is modified  in a non-rigid  (that
is,  asymmetric)  affixment,  the  effect is to move  the subsidiary
frame.   If  the value  of the  trans  changes in  a rigid  
(symmetric) affixment, then neither frame will change its value until
one of them  explicitly gets a new value; at that time the other will spring
to a new position, as determined by the trans.

The inclusion of the construct "AT#<trans#expression>" will cause
'AL to use the indicated value for the relative affixed position of the
objects.  Thus,

.UNFILL
	AFFIX pump TO base AT NILTRANS

.bull
is equivalent to

	TRANS tempxf;
	AFFIX pump TO base BY tempxf;
	TEMPXF ← NILTRANS

.Bull
Similarly,

	TRANS XF;
	AFFIX pump TO base BY xf AT TRANS(NILROT,Z);
.BULL
is equivalent to

	TRANS XF;
	AFFIX pump TO base BY xf;
	xf ← TRANS(NILROT,Z);
.REFILL
	It  is  possible to  make  chains of  affixments,   possibly
involving some rigid affixments and some non-rigid ones.


.NEWSSS THE UNFIX STATEMENT
Affixments are undone by the UNFIX statement.  For example,
.UNFILL
	UNFIX pump FROM base
.REFILL
will remove the affix structure between pump and base,  and will discard
the invented trans  (unless it was named, of course).
Similarly, the compiler's planning model will be updated to reflect
the fact that pump and base are no longer affixed. However, the
fact that they were previously affixed is important for calculation
of default "deproaches" ({SSREF dep}), and is remembered until either
of the two frames is changes.  See {sssref gaf} for a more detailed
description of the assertions actually made do do this.

.NEWSSS  MOTIONS AND AFFIXMENT

	When some frame has been affixed to an arm, it can be treated
as if it were itself an arm.  Thus, the following is legal and useful:
.UNFILL
	FRAME frob, frobgrasp;
	:
	AFFIX frobgrasp TO frob;
	AFFIX frob TO yellow;
	:
	MOVE frobgrasp TO ⊗ + (Z WRT frob);
.REFILL
The effect of this motion statement is to cause the yellow arm
to move in such a way that frobgrasp moves one centimeter
in frob's Z direction.  The compiler notices that frobgrasp is
affixed to frob, which in turn is affixed to yellow; furthermore,
it knows the relative positions of each of these, so it is not
too hard to translate  the given motion statement into a statement
dealing only with the yellow arm.  It is a great convenience to
let the compiler do this translation, which can get messy in the
presence of complicated affixment structures.

The use of "⊗" inside a motion always refers to the frame being treated
as an arm, whether it is actually an arm (blue, yellow) or an affixed
frame (frobgrasp).

If some frame is attached to more than one arm, then it is not legal
to use this feature, because the compiler would have no way of
determining which arm to use.  Actually, such an attempt is most
likely an error on the user's part; if an object is affixed to
both arms, then they are joined through that object.  It is therefore
not safe to move one arm and not the other.  The "right" thing to
do in such a case would be move all the relevant arms to the appropriate
places.  We do not intend to implement this at first.